/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Platform } from 'react-native';
import { createHarmonyGesture } from '../native/harmonyGesture';
import { createNativeGesture } from '../native/nativeGesture';
import { Gesture as RnGesture } from 'react-native-gesture-handler';

export type GestureType =
  | 'pan'
  | 'tap'
  | 'longPress'
  | 'rotation'
  | 'pinch'
  | 'fling'
  | 'hover';

export type GestureMethods = {
  minPointers(n: number): GestureMethods;
  minDistance(n: number): GestureMethods;
  direction(v: string): GestureMethods;
  minVelocity(n: number): GestureMethods;
  numberOfTaps(n: number): GestureMethods;
  minDuration(n: number): GestureMethods;
  minAngle(n: number): GestureMethods;
  repeat(value: boolean): GestureMethods;

  onStart(cb: (event: GestureEvent) => void): GestureMethods;
  onUpdate(cb: (event: GestureEvent) => void): GestureMethods;
  onEnd(cb: (event: GestureEvent) => void): GestureMethods;
  onCancel(cb: (event: GestureEvent) => void): GestureMethods;
  onHover?(cb: (event: any) => void): GestureMethods;

  gesture?: any;
  __gestureConfig: Record<string, any>;
};

interface TapGesture {
  numberOfTaps(n: number): this;
  minPointers(n: number): this;
  onStart(cb: (event: GestureEvent) => void): this;
}

interface LongPressGesture {
  repeat(value: boolean): this;
  minDuration(n: number): this;
  minPointers(n: number): this;
  onStart(cb: (event: GestureEvent) => void): this;
  onCancel(cb: (event: GestureEvent) => void): this;
  onEnd(cb: (event: GestureEvent) => void): this;
}

interface PanGesture {
  minPointers(n: number): this;
  minDistance(n: number): this;
  direction(v: string): this;
  onUpdate(cb: (event: GestureEvent) => void): this;
  onStart(cb: (event: GestureEvent) => void): this;
  onCancel(cb: (event: GestureEvent) => void): this;
  onEnd(cb: (event: GestureEvent) => void): this;
}

interface RotationGesture {
  minPointers(n: number): this;
  minAngle(n: number): this;
  onUpdate(cb: (event: GestureEvent) => void): this;
  onStart(cb: (event: GestureEvent) => void): this;
  onCancel(cb: (event: GestureEvent) => void): this;
  onEnd(cb: (event: GestureEvent) => void): this;
}

interface PinchGesture {
  minPointers(n: number): this;
  minDistance(n: number): this;
  onUpdate(cb: (event: GestureEvent) => void): this;
  onStart(cb: (event: GestureEvent) => void): this;
  onCancel(cb: (event: GestureEvent) => void): this;
  onEnd(cb: (event: GestureEvent) => void): this;
}

interface FlingGesture {
  minPointers(n: number): this;
  minVelocity(n: number): this;
  direction(v: string): this;
  onStart(cb: (event: GestureEvent) => void): this;
  onCancel(cb: (event: GestureEvent) => void): this;
}

interface HoverGesture {
  onHover(cb: (event: any) => void): this;
}

type GestureMap = {
  pan: PanGesture;
  tap: TapGesture;
  longPress: LongPressGesture;
  rotation: RotationGesture;
  pinch: PinchGesture;
  fling: FlingGesture;
  hover: HoverGesture;
};

type GestureEvent = {
  absoluteX: number;
  absoluteY: number;
  handlerTag: number;
  numberOfPointers: number;
  oldState: number;
  state: number;
  x: number;
  y: number;
  translationX: number;
  translationY: number;
  velocityX: number;
  velocityY: number;
  anchorX: number;
  anchorY: number;
  rotation: number;
  velocity: number;
  duration: number;
  focalX: number;
  focalY: number;
  scale: number;
  repeat: boolean;
  fingers: FingerData[];
  type: string;
  timestamp: number;
};

export type FingerData = {
  pointId: number;
  x: number;
  y: number;
  windowX: number;
  windowY: number;
  displayX: number;
  displayY: number;
  tiltX: number;
  tiltY: number;
};

function createTypedGesture<T extends GestureType>(type: T): GestureMap[T] {
  const gesture =
    Platform.OS === 'harmony'
      ? createHarmonyGesture(type)
      : createNativeGesture(type);

  return gesture as GestureMap[T];
}

export const Gesture = {
  Pan: (): GestureMap[GestureType] => createTypedGesture('pan'),
  Tap: (): GestureMap[GestureType] => createTypedGesture('tap'),
  LongPress: (): GestureMap[GestureType] => createTypedGesture('longPress'),
  Rotation: (): GestureMap[GestureType] => createTypedGesture('rotation'),
  Pinch: (): GestureMap[GestureType] => createTypedGesture('pinch'),
  Fling: (): GestureMap[GestureType] => createTypedGesture('fling'),
  Hover: (): GestureMap[GestureType] => createTypedGesture('hover'),
  // 新增组合手势方法
  Simultaneous: (...gestures: any[]): any => {
    if (Platform.OS === 'harmony') {
      return { type: 'simultaneous', gestures };
    }
    return {
      gesture: RnGesture.Simultaneous(...gestures.map(g => g.gesture || g)),
    };
  },
  Race: (...gestures: any[]): any => {
    if (Platform.OS === 'harmony') {
      return { type: 'race', gestures };
    }
    return {
      gesture: RnGesture.Race(...gestures.map(g => g.gesture || g)),
    };
  },
  Exclusive: (...gestures: any[]): any => {
    if (Platform.OS === 'harmony') {
      return { type: 'exclusive', gestures };
    }
    return {
      gesture: RnGesture.Exclusive(...gestures.map(g => g.gesture || g)),
    };
  },
};
